#include <Imx.h>
#include <queue>
#include "util.h"
#include "can.h"
#include "crc.h"
#include "config.h"
#include "global.h"

using namespace std;
using namespace Imx;

void
print_frame(struct can_frame * frame)
{
	u8 i;
	printf("CAN ID[0x%08x] ==> ",frame->can_id);
	for(i=0;i<8;i++)
	{
		printf("[0x%02x]",frame->data[i]);
	}
	printf("\n");
}

void
print_report(ChnReport *rep)
{
	printf("============================\n");
	printf("    chnNo       => [0x%02x]\n",rep->chnNo);
	printf("    workMode    => [0x%02x]\n",rep->workMode);
	printf("    workState   => [0x%02x]\n",rep->workState);
	printf("    retCode     => [0x%02x]\n",rep->retCode);
	printf("    voltage     => [0x%08x]\n",rep->voltage);
	printf("    current     => [0x%08x]\n",rep->current);
	printf("    temperature => [0x%08x]\n",rep->temperature);
	printf("    timestamp   => [0x%08x]\n",rep->timestamp);
	printf("============================\n");
}

Analysis::Analysis()
{
	_stopped = false;
	_hasHead = false;
}

// 处理采集数据   
// 注：因为知道数据长度所以使用固定代码取处理
void
Analysis::process_DATA_ACK()
{
	struct can_frame frame;
	ChnReport cReport;
	u8	len,i,devId;
	u16	crc16,crc16check;
	u8	idx;

	// pkt head
	frame = _chnReportQueue.front();
	_chnReportQueue.pop();
	len = (frame.can_id & PKT_LEN_MASK)>> 8;
	devId = (frame.can_id & 0xFF);
	memcpy(&cReport, frame.data, 8);
	len -= 8;

	// pkt body
	frame = _chnReportQueue.front();
	_chnReportQueue.pop();
	memcpy(&cReport.current, frame.data, 8);
	len -= 8;

	// pkt tail
	frame = _chnReportQueue.front();
	_chnReportQueue.pop();
	memcpy(&cReport.timestamp, frame.data, 4);

	// crc
	crc16 = frame.data[4] | (frame.data[5] << 8);


	crc16check = getCrc16((u8 *)&cReport, sizeof(cReport) - 4);

	idx = frame.data[6];
	//printf("[%d]\n",idx);
	//printf(" crc[%x]   check[%x]\n",crc16,crc16check);

	//print_report(&cReport);
	
	// 数据处理
	gDataManager.updateChn(devId,cReport);
}

// 处理心跳应答
// 注：修改对应的设备状态位，并重置超时计数。
void
Analysis::process_HB_ACK(u8 devId)
{
	gDataManager.hbReset(devId);
}

extern struct timespec start_ts;
struct timespec end_ts;
int k =0;
void
Analysis::run()
{
	struct can_frame frame;
	u32 type;
	u32 cmd;
	u8	devId;

	while(!_stopped)
	{
		frame = can0.popFrame();

		type = frame.can_id & PKT_TYPE_MASK;
		cmd = frame.can_id & PKT_CMD_MASK;
		//printf("type[0x%08x]  cmd[0x%08x]\n",type,cmd);
		switch(cmd)
		{
			case DCMD_HB_ACK:
				//printf(">>>...DCMD_HB_ACK\n");
				devId = (u8)(frame.can_id & PKT_ID_MASK);
				process_HB_ACK(devId);
				/*
						clock_gettime(CLOCK_REALTIME, &end_ts);
						printf(" s[%ld]  ns[%ld]\n" ,end_ts.tv_sec, end_ts.tv_nsec);
				*/
				break;
			case DCMD_DATA_ACK:
				_chnReportQueue.push(frame);
				if(type == TYPE_TAIL)
				{
				//printf(">>>...DCMD_DATA_ACK\n");
					k++;
					process_DATA_ACK();
					_hasHead = false;
				}
				if(type == TYPE_HEAD)			// 处理时收到头部表示上一组消息尾部丢失
				{
					if(_hasHead)
					{
						while(!_chnReportQueue.empty())	// 清理临时队列
						{
							_chnReportQueue.pop();
						}
						_chnReportQueue.push(frame);		//
					}
					else
					{
						_hasHead = true;
					}
				}
				break;
			case DCMD_SET_ACK:
				//printf(">>>...DCMD_SET_ACK\n");
				can0.setPutAck(frame); // 应答存入处理队列，唤醒处理线程
				break;
			case DCMD_STEP_ACK:
				//printf(">>>...DCMD_STEP_ACK\n");
				gTaskManager.processAck(frame);  // 应答存入处理队列，唤醒处理线程
				break;
			case DCMD_FIN_ACK:
				//printf(">>>...DCMD_IDLE_ACK\n");
				gTaskManager.processAck(frame);  // 应答存入处理队列，唤醒处理线程
				break;
			default:
				break;
		}
	}
}


